/*
    This is a set of libraries to assist in OpenGl and Other Applications
    Copyright (C) 2008  The Modular Engine Team

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef OPENGLMODULE_H
#define OPENGLMODULE_H
#undef _WINGDI_H
#include <list>
#include <windows.h>
#include <gl/gl.h>
#include <gl/glu.h>
#include "math.h"
#include "EngineCore.h"
#include "Texture.h"
//#include "GraphicsModule.h"
//#include "WindowModule.h"

// include all libs needed
#pragma comment( lib, "user32.lib" )
#pragma comment( lib, "opengl32.lib" )
#pragma comment( lib, "glu32.lib" )
#pragma comment( lib, "Gdi32.lib" )

#undef CLASSDECL
#ifdef OPENGLMODULE
	#define CLASSDECL __declspec(dllexport)
#else
	#pragma comment( lib, "OpenglModule.lib" )
	#define CLASSDECL __declspec(dllimport)
#endif

//#include "ImageLoader.h"

// The module for opengl loading and everything.

namespace ModularEngine
{



	/// Interfaces ModularEngine to Opengl

	/// Soon to be deprecated module for Opengl
	/// Hopefully soon an OpenglModule with a parent of GraphicsInterfaceBase
	/// will be created.
	class CLASSDECL OpenglModule: BASE(OpenglModule)
	{
	protected:
		/// Opengl Initialization Stuff
		HGLRC mhRC;
		HDC mhDC;
		UINT mPixelFormat;
		HWND mHwnd;

		/// following used for drawing text on screen
		HFONT mhFont;
		LOGFONT mLogFont;
		UINT mFontList;

		/// Functor for loading textures
		LoadTextureFunctor *texLoader;
	
		/// TODO: Change texture list to vector for easy texture unloading.
		std::list<TextureID> mlTextures;
		
	public:

		OpenglModule()
		{
			mHwnd = 0;
			texLoader = 0;
		}

		/// Setup opengl with windows
		int initialize();
		/// Swap buffers and clear the background.
		int run();
		
		/// Set Window Handle
		void setWindowHandle( HWND hWnd );

		/// glClearColor()
		void clearColor( Vector3d vColor );

		/// will draw a rectangle w/ 2 Vector2d.  
		/// vPos is x, y coords  
		/// vDims is height and width
		void drawRect( Vector2d vPos, Vector2d vDims ); 

		/// Draw a rect w/ a gradient
		void drawGradientRect( Vector2d vPos, Vector2d vDims, Vector3d vStartColor, Vector3d vEndColor, bool horizontal = false );

		/// draw's an image at it's original dimensions
		void drawImage( char *pImage, Vector2d vPos );
		void drawImage( char *pImage, Vector2d vPos, Vector2d vDims );

		/// loadTexture checks if pTexturePath is already loaded.
		/// if not it loads it.  Returns -1 if error.  Any other number is opengl texture id.
		/// pTexturePath can also be the macro name.
		TextureID *loadTexture( char *pTexturePath, char *pMacro = 0 );

		/// sets the viewport to the correct sizes.
		void resizeWindow( int width, int height );
		
		/// Checks if point is in rectangle.
		bool pointInRect( Vector2d vPoint, Vector2d vPos, Vector2d vDims );

		/// Draws Text To Screen
		void drawText( char *text, Vector2d vPos );

		/// Set functor for loading textures:
		void setLoadTextureFunctor( LoadTextureFunctor *func );

		/// Draw a bezier curve using points.
		/// If t is -1 then, draw whole line.
		void drawBezier( Vector3d *points, int nPoints, float interval);
		Vector3d drawBezierProc( Vector3d *points, int nPoints, float t );

		void drawCubicHermite( Vector3d *points, float c, float interval );
		Vector3d drawCubicHermiteProc( Vector3d *points, float c, float t );

		/// Sets the coordinates to be relative to whatever the user wants
		/// probably a better way of explaining that.  
		/// Basically if a user has a window at 40,50, he sets the relative
		/// coordinates to that and then he can draw at 0, 0 and that'll be
		/// 0, 0 relative to the window.
		void setCoords( Vector2d vVec );

		/// glLoadIdentity()
		void resetCoords();

	};
}

#endif
